home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / gsdbloo.exe / GS_EDIT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-02-24  |  22.3 KB  |  772 lines

  1. Unit GS_Edit;
  2. {-----------------------------------------------------------------------------
  3.                                  Editor Routines
  4.  
  5.        GS_Edit Copyright (c)  Richard F. Griffin
  6.  
  7.        10 January 1991
  8.  
  9.        102 Molded Stone Pl
  10.        Warner Robins, GA  31088
  11.  
  12.        -------------------------------------------------------------
  13.        This unit handles the objects for a simple editor similar to
  14.        WordStar.
  15.  
  16.        Changes:
  17.  
  18.        18 May 91 - Modified Presssed_Del to bring up the succeeding line
  19.                    if the cursor is at the end of the line.
  20.  
  21.        06 Jun 91 - Modified startup routine to initialize the windows.  all
  22.                    instances will use the same window object.
  23.  
  24.        20 Feb 92 - Added a Done destructor to allow dynamic allocation and
  25.                    deallocation of the object.
  26.  
  27. ------------------------------------------------------------------------------}
  28.  
  29. interface
  30. {$D-}
  31.  
  32. uses
  33.    CRT,
  34.    Dos,
  35.    GS_KeyI,
  36.    GS_Scrn,
  37.    GS_Winfc,
  38.    GS_Error,
  39.    GS_Strng;
  40. type
  41.    GS_Edit_Pntr = ^GS_Edit_Line;
  42.    GS_Edit_Line = record
  43.                      Next_Line,
  44.                      Prev_Line  : GS_Edit_Pntr;
  45.                      Return_Cod : byte;
  46.                      Line_Size  : integer;
  47.                      Valu_Line  : string;
  48.                   end;
  49.  
  50.    GS_Edit_Blok = record
  51.                      Blok_Line,
  52.                      Blok_Colm  : integer;
  53.                   end;
  54.  
  55.    GS_Edit_Objt = object
  56.                      First_Line,
  57.                      End_Line,
  58.                      Work_Line   : GS_Edit_Pntr;
  59.                                       {Used to track lines}
  60.                      Cursor_LocX,
  61.                      Cursor_LocY : word;
  62.                                       {Hold cursor location}
  63.                      Active_Line,     {Current line number}
  64.                      Total_Lines,     {Total number of lines}
  65.                      Screen_Top,      {Line number at top of screen}
  66.                      Screen_Btm  : longint;
  67.                                       {Line Number at bottom of screen}
  68.                      CursorPos   : integer;
  69.                                       {Position in line}
  70.                      CursorLine  : integer;
  71.                                       {Line currently working on}
  72.                      Temp_Line   : string;
  73.                                       {work area during wordwrap}
  74.                      Edit_Lgth   : integer;
  75.                                       {Max size of eaach line}
  76.                      Lines_Avail : integer;
  77.                                       {Number of lines that will fit in the}
  78.                                       {window on the screen}
  79.                      Ch_Work     : char;
  80.                                       {Hold area for keystrokes}
  81.                      Word_Wrap   : boolean;
  82.                                       {True sets word wrap on}
  83.                      WW_Flag     : boolean;
  84.                                       {Internal flag for wordwrap condition}
  85.                      Blok_Begin,
  86.                      Blok_Fini   : GS_Edit_Blok;
  87.                                       {Future use for block operations}
  88.  
  89.  
  90.                      constructor Init;
  91.                      destructor  Done;
  92.                      function    Byte_Count : longint;
  93.                      procedure   Check_Func_Keys;
  94.                      procedure   Clear_Editor;
  95.                      procedure   Edit;
  96.                      Procedure   Edit_Line;
  97.                      function    Find_Line(linenum : integer) : boolean;
  98.                      function    Get_Line_Mem(lth : integer) : pointer;
  99.                      Procedure   Rel_Line_Mem(linenum : integer);
  100.                      Procedure   Show_Lines(b, e :integer);
  101.                      Procedure   View;
  102.                      Procedure   WordWrap(Fline : string);
  103.                      Procedure   Pressed_Bsp;
  104.                      Procedure   Pressed_CrtlY;
  105.                      Procedure   Pressed_Del;
  106.                      Procedure   Pressed_DnAr;
  107.                      Procedure   Pressed_F1;
  108.                      Procedure   Pressed_Ret;
  109.                      Procedure   Pressed_UpAr;
  110.                      Procedure   Pressed_PgUp;
  111.                      Procedure   Pressed_PgDn;
  112.                   end;
  113.  
  114.  
  115. implementation
  116. var
  117.    StatWin,
  118.    HelpWin,
  119.    EditWin  : GS_Wind_Objt;
  120.  
  121. constructor GS_Edit_Objt.Init;
  122. begin
  123.    First_Line := nil;
  124.    End_Line := nil;
  125.    Work_Line := nil;
  126.    Word_Wrap := true;
  127.    WW_Flag := false;
  128.    Active_Line := 0;
  129.    Total_Lines := 0;
  130.    Screen_Top := 0;
  131.    Screen_Btm := 0;
  132.    Ch_Work := #0;
  133.    CursorPos := 1;
  134.    CursorLine := 1;
  135.    Temp_Line := '';
  136.    GS_KeyI_Ins := True;               {Start in insert mode}
  137.    Edit_Lgth := 32;
  138. end;
  139.  
  140. destructor GS_Edit_Objt.Done;
  141. begin
  142.    Clear_Editor;
  143. end;
  144.  
  145. function GS_Edit_Objt.Byte_Count : longint;
  146. var
  147.    i : longint;
  148.    p : GS_Edit_Pntr;
  149. begin
  150.    i := 0;
  151.    p := First_Line;
  152.    while (p <> nil) do
  153.    begin
  154.       i := i + length(p^.Valu_Line) + 2;
  155.                                       {Add length of line + CR/LF chars}
  156.       p := p^.Next_Line;
  157.    end;
  158.    inc(i);                            {Add one for EOF byte}
  159.    Byte_Count := i;
  160. end;
  161.  
  162. procedure GS_Edit_Objt.Clear_Editor;
  163. begin
  164.    Work_Line := First_Line;
  165.    while (Work_Line <> nil) do
  166.    begin
  167.       End_Line := Work_Line^.Next_Line;
  168.       FreeMem(Work_Line,Work_Line^.Line_Size);
  169.       Work_Line := End_Line;
  170.    end;
  171.    First_Line := nil;
  172.    End_Line := nil;
  173.    Work_Line := nil;
  174.    Active_line := 0;
  175.    Total_Lines := 0;
  176. end;
  177.  
  178.  
  179. procedure GS_Edit_Objt.Pressed_F1;
  180. var
  181.    cc : char;
  182. begin
  183.    HelpWin.SetWin;
  184.    writeln('Toggle Ins  - Ins');
  185.    writeln('Delete Char - Del');
  186.    writeln('Delete Line - Ctl-Y');
  187.    writeln('Press any Key');
  188.    cc := ReadKey;
  189.    if cc = #0 then cc := ReadKey;
  190.    HelpWin.RelWin;
  191. end;
  192.  
  193.  
  194. procedure GS_Edit_Objt.Pressed_Bsp;
  195. var
  196.    bb : byte;
  197.    ss : string;
  198.    ll : boolean;
  199. begin
  200.    if CursorPos > 1 then
  201.    begin
  202.       Delete(Work_Line^.Valu_Line, Pred(CursorPos), 1);
  203.       GoToXY(1, CursorLine);
  204.       Write(Work_Line^.Valu_Line);
  205.       ClrEol;
  206.       Dec(CursorPos);
  207.    end
  208.    else
  209.    begin
  210.       if Active_Line > 1 then
  211.       begin
  212.          bb := Work_line^.Return_Cod;
  213.          ss := Work_Line^.Valu_Line;
  214.          if Active_Line < Total_Lines then
  215.          begin
  216.             Pressed_CrtlY;
  217.             Pressed_UpAr;
  218.          end else Pressed_CrtlY;
  219.          Work_Line^.Return_Cod := bb;
  220.          ss := Work_Line^.Valu_Line + ss;
  221.          CursorPos := length(Work_Line^.Valu_Line);
  222.          WordWrap(ss);
  223.          GotoXY(1,succ(Active_Line-Screen_Top));
  224.          write(Work_Line^.Valu_Line);
  225.       end;
  226.    end;
  227. end;
  228.  
  229. procedure GS_Edit_Objt.Pressed_Del;
  230. begin
  231.    if CursorPos <= Length(Work_Line^.Valu_Line) then
  232.    begin
  233.       Delete(Work_Line^.Valu_Line, CursorPos, 1);
  234.       GoToXY(1, CursorLine);
  235.       Write(Work_Line^.Valu_Line);
  236.       ClrEol;
  237.    end
  238.    else
  239.    begin
  240.       if Active_Line < Total_Lines then
  241.       begin
  242.          Pressed_DnAr;
  243.          CursorPos := 1;
  244.          Pressed_Bsp;
  245.       end;
  246.    end;
  247. end;
  248.  
  249. procedure GS_Edit_Objt.Pressed_PgDn;
  250. begin         {Page Down}
  251.    Active_Line := pred(Screen_Top + Lines_Avail);
  252.    if Active_Line > Total_Lines then Active_Line := Total_Lines;
  253.    if not Find_Line(Active_Line) then
  254.    begin
  255.       ShowError(710,'Pressed_PgDn');
  256.       exit;
  257.    end;
  258.    if Active_Line <> Screen_Top then Show_Lines(Active_Line,Total_Lines);
  259.    CursorLine := 1;
  260.    if length(Work_Line^.Valu_Line)+1 < CursorPos then
  261.       CursorPos := length(Work_Line^.Valu_Line)+1;
  262. end;
  263.  
  264. procedure GS_Edit_Objt.Pressed_PgUp;
  265. begin         {Page Up}
  266.    if Active_Line <= 1 then exit;
  267.    Active_Line := succ(Screen_Top - Lines_Avail);
  268.    if Active_Line < 1 then Active_Line := 1;
  269.    if not Find_Line(Active_Line) then
  270.    begin
  271.       ShowError(710,'Pressed_PgUp');
  272.       exit;
  273.    end;
  274.    if Active_Line < Screen_Top then Show_Lines(Active_Line,Total_Lines);
  275.    CursorLine := 1;
  276.    if length(Work_Line^.Valu_Line)+1 < CursorPos then
  277.       CursorPos := length(Work_Line^.Valu_Line)+1;
  278. end;
  279.  
  280. procedure GS_Edit_Objt.Pressed_UpAr;
  281. begin         {Up Arrow}
  282.    if Active_Line <= 1 then exit;
  283.    if not Find_Line(pred(Active_Line)) then
  284.    begin
  285.       ShowError(710,'Pressed_UpAr');
  286.       exit;
  287.    end;
  288.    if Active_Line < Screen_Top then
  289.    begin
  290.       gotoxy(1,1);
  291.       InsLine;
  292.       dec(Screen_Top);
  293.       write(Work_Line^.Valu_Line);
  294.    end;
  295.    if length(Work_Line^.Valu_Line)+1 < CursorPos then
  296.       CursorPos := length(Work_Line^.Valu_Line)+1;
  297. end;
  298.  
  299. procedure GS_Edit_Objt.Pressed_DnAr;
  300. begin         {Down Arrow}
  301.    if Active_Line >= Total_Lines then exit;
  302.    if not Find_Line(succ(Active_Line)) then
  303.    begin
  304.       ShowError(710,'Pressed_DnAr');
  305.       exit;
  306.    end;
  307.    if Active_Line-Screen_Top >= Lines_Avail then
  308.    begin
  309.       GoToXY(1,1);
  310.       DelLine;
  311.       inc(Screen_Top);
  312.       GotoXY(1,Lines_Avail);
  313.       write(Work_Line^.Valu_Line);
  314.    end;
  315.    if length(Work_Line^.Valu_Line)+1 < CursorPos then
  316.    CursorPos := length(Work_Line^.Valu_Line)+1;
  317. end;
  318.  
  319.  
  320. procedure GS_Edit_Objt.Pressed_Ret;
  321. begin         {Return}
  322.    GS_KeyI_Ret := true;
  323.    Work_Line^.Return_Cod := $0D;
  324.    if GS_KeyI_Ins then
  325.    begin
  326.       ClrEol;
  327.       Temp_Line := Work_Line^.Valu_Line;
  328.       Work_Line^.Valu_Line := substr(Work_Line^.Valu_Line,1,pred(CursorPos));
  329.       delete(Temp_Line,1,pred(CursorPos));
  330.       Work_Line := Get_Line_Mem(Edit_Lgth);
  331.       Work_Line^.Valu_Line  := Temp_Line;
  332.       if Active_Line-Screen_Top >= Lines_Avail then
  333.       begin
  334.          GoToXY(1,1);
  335.          DelLine;
  336.          inc(Screen_Top);
  337.          GotoXY(1,Lines_Avail);
  338.          write(Work_Line^.Valu_Line);
  339.       end else
  340.       begin
  341.          GotoXY(1,succ(CursorLine));
  342.          InsLine;
  343.          write(Work_Line^.Valu_Line);
  344.       end;
  345.    end
  346.    else
  347.    begin
  348.       if Active_Line-Screen_Top >= Lines_Avail then
  349.       begin
  350.          GoToXY(1,1);
  351.          DelLine;
  352.          inc(Screen_Top);
  353.       end;
  354.       if not Find_Line(succ(Active_Line)) then
  355.       Work_Line := Get_Line_Mem(Edit_Lgth);
  356.       GotoXY(1,CursorLine);
  357.       write(Work_Line^.Valu_Line);
  358.    end;
  359.    CursorPos := 1;
  360. end;
  361.  
  362. procedure GS_Edit_Objt.Pressed_CrtlY;
  363. var
  364.    p : GS_Edit_Pntr;
  365. begin
  366.    if Total_Lines <= 1 then
  367.    begin
  368.       if not Find_Line(1) then
  369.       begin
  370.          SoundBell(BeepTime,BeepFreq);
  371.          ShowError(750,'Lost track of edit line');
  372.          exit;
  373.       end;
  374.       Work_Line^.Valu_Line := '';
  375.       DelLine;
  376.       exit;
  377.    end;
  378.    Rel_Line_Mem(Active_Line);
  379.    DelLine;
  380.    p := Work_Line;
  381.    CursorLine := succ(Active_Line-Screen_Top);
  382.    if length(Work_Line^.Valu_Line)+1 < CursorPos then
  383.       CursorPos := length(Work_Line^.Valu_Line)+1;
  384.    Show_Lines(Screen_Top,Total_Lines);
  385. end;
  386.  
  387.  
  388. procedure GS_Edit_Objt.Check_Func_Keys;
  389. var
  390.    i : integer;
  391. begin
  392.    case Ch_Work of
  393.             Kbd_F1    : Pressed_F1;
  394.             Kbd_Home  : CursorPos := 1;
  395.             Kbd_End   : CursorPos := Succ(Length(Work_Line^.Valu_Line));
  396.             Kbd_Ins   : begin
  397.                            GS_KeyI_Ins := not GS_KeyI_Ins;
  398.                            GS_Scrn_SetCursor(GS_KeyI_Ins);
  399.                         end;
  400.             Kbd_LfAr  : if CursorPos > 1 then Dec(CursorPos);
  401.             Kbd_RtAr  : if CursorPos <= Length(Work_Line^.Valu_Line) then Inc(CursorPos);
  402.             Kbd_Bsp   : Pressed_Bsp;
  403.             Kbd_Del   : Pressed_Del;
  404.             Kbd_PgUp  : Pressed_PgUp;
  405.             Kbd_PgDn  : Pressed_PgDn;
  406.             Kbd_UpAr  : Pressed_UpAr;
  407.             Kbd_DnAr :  Pressed_DnAr;
  408.             Kbd_Ret   : Pressed_Ret;
  409.             Kbd_Esc   : GS_KeyI_Esc := True;
  410.             #25       : Pressed_CrtlY;  {CTRL-Y}
  411.  
  412.    end;
  413. end;
  414.  
  415. {
  416.          ┌──────────────────────────────────────────────────────────┐
  417.          │  ********        Edit String Procedure         *******   │
  418.          │                                                          │
  419.          │  This is the main method to edit an input string.  The   │
  420.          │  usual cursor keys are processed through a method that   │
  421.          │  may be replaced by a child object's virtual method.     │
  422.          │  The Escape key will terminate and return the default    │
  423.          │  value to the calling program.                           │
  424.          └──────────────────────────────────────────────────────────┘
  425. }
  426.  
  427.  
  428. Procedure GS_Edit_Objt.Edit_Line;
  429. var
  430.    t1 : string;
  431.    lc,
  432.    xl,
  433.    yl,
  434.    i  : integer;
  435. begin
  436.    if Work_Line = nil then
  437.       Work_Line := Get_Line_Mem(Edit_Lgth);
  438.    Insert(Ch_Work, Work_Line^.Valu_Line, CursorPos);
  439.    Inc(CursorPos);                {Step to the next location in the string}
  440.    if not GS_KeyI_Ins then delete(Work_Line^.Valu_Line, CursorPos, 1);
  441.    GoToXY(1, CursorLine);
  442.    Write(Work_Line^.Valu_Line);
  443.    if length(Work_Line^.Valu_Line) >= Edit_Lgth then
  444.       WordWrap(Work_Line^.Valu_Line);
  445. end; { Edit_Line }
  446.  
  447. procedure GS_Edit_Objt.Edit;
  448. var
  449.    stx : string;
  450. begin
  451.    StatWin.SetWin;
  452.    write(' F1 for Help    CTRL-END to Quit    ESC to Abort');
  453.    EditWin.SetWin;
  454.    WW_Flag := false;
  455.    Screen_Top := 0;
  456.    Screen_Btm := 0;
  457.    Ch_Work := #0;
  458.    CursorPos := 1;
  459.    CursorLine := 1;
  460.    Temp_Line := '';
  461.    GS_KeyI_Ins := True;               {Start in insert mode}
  462.    GS_KeyI_Esc := False;              {Set the Escape flag false}
  463.    GS_KeyI_Ret := false;              {Set Return flag false}
  464.    Cursor_LocX := WhereX;
  465.    Cursor_LocY := WhereY;
  466.    Lines_Avail := hi(WindMax) - hi(WindMin);
  467.    inc(Lines_Avail);                  {Adjust for correct number}
  468.    GS_Scrn_SetCursor(GS_KeyI_Ins);    {Go set cursor size}
  469.    if First_Line = nil then
  470.       Work_Line := Get_Line_Mem(Edit_Lgth)
  471.    else
  472.    begin
  473.       Work_Line := First_Line;
  474.       Active_Line := 1;
  475.    end;
  476.    Show_Lines(1,Lines_Avail);
  477.    repeat
  478.       window(1,24,80,24);
  479.       gotoxy(55,1);
  480.       write('Col: ',CursorPos:2,'   Line: ',Active_Line,'':4);
  481.       window(EditWin.X1,EditWin.Y1,EditWin.X2,EditWin.Y2);
  482.       CursorLine := succ(Active_Line-Screen_Top);
  483.       GotoXY(CursorPos, CursorLine);  {Go to current position in the screen}
  484.                                       {write updated part of line}
  485.       Ch_Work := GS_KeyI_GetKey;      {Get the next keyboard entry}
  486.       if (GS_KeyI_Fuc) or (Ch_Work in [#0..#31]) then
  487.                                       {See if function key or control char}
  488.          Check_Func_Keys              {If it is, go process it.}
  489.       else                            {Otherwise add character to the string}
  490.          Edit_Line;                   {Go add character to the line}
  491.    until ((GS_KeyI_Chr = Kbd_CEnd) and
  492.          (GS_KeyI_Fuc)) or (GS_KeyI_Esc);
  493.                                       {Continue until Ctrl-End or Esc pressed}
  494.    GS_Scrn_SetCursor(False);          {Set cursor size to small cursor}
  495.    GS_KeyI_Ins := False;
  496.    EditWin.RelWin;
  497.    StatWin.RelWin;
  498. end;
  499.  
  500.  
  501. procedure GS_Edit_Objt.View;
  502. var
  503.    stx : string;
  504. begin
  505.    StatWin.SetWin;
  506.    write('ESC When Done':45);
  507.    EditWin.SetWin;
  508.    WW_Flag := false;
  509.    Screen_Top := 0;
  510.    Screen_Btm := 0;
  511.    Ch_Work := #0;
  512.    CursorPos := 1;
  513.    CursorLine := 1;
  514.    Temp_Line := '';
  515.    GS_KeyI_Ins := True;               {Start in insert mode}
  516.    GS_KeyI_Esc := False;              {Set the Escape flag false}
  517.    GS_KeyI_Ret := false;              {Set Return flag false}
  518.    Cursor_LocX := WhereX;
  519.    Cursor_LocY := WhereY;
  520.    Lines_Avail := hi(WindMax) - hi(WindMin);
  521.    inc(Lines_Avail);                  {Adjust for correct number}
  522.    if First_Line = nil then
  523.       Work_Line := Get_Line_Mem(Edit_Lgth)
  524.    else
  525.    begin
  526.       Work_Line := First_Line;
  527.       Active_Line := 1;
  528.    end;
  529.    Show_Lines(1,Lines_Avail);
  530.    repeat
  531.       Ch_Work := GS_KeyI_GetKey;      {Get the next keyboard entry}
  532.       if (GS_KeyI_Fuc) or (Ch_Work in [#0..#31]) then
  533.       case Ch_Work of
  534.          Kbd_PgUp : Pressed_PgUp;
  535.          Kbd_PgDn : Pressed_PgDn;
  536.       end;
  537.    until (Ch_Work = Kbd_Esc);
  538.                                       {Continue until Ctrl-End or Esc pressed}
  539.    GS_KeyI_Ins := False;
  540.    EditWin.RelWin;
  541.    StatWin.RelWin;
  542. end;
  543.  
  544. function GS_Edit_Objt.Find_Line(linenum : integer) : boolean;
  545. var
  546.    i : integer;
  547. begin
  548.    if linenum > Total_Lines then
  549.    begin
  550.       Find_Line := false;
  551.       exit;
  552.    end;
  553.    if First_Line = nil then Work_Line := nil
  554.    else
  555.    begin
  556.       Work_Line := First_Line;
  557.       i := 1;
  558.       while (i < linenum) and (Work_Line <> nil) do
  559.       begin
  560.          Work_Line := Work_Line^.Next_Line;
  561.          inc(i);
  562.       end;
  563.    end;
  564.    if Work_Line = nil then
  565.    begin
  566.       Find_line := false;
  567.       ShowError(710,'Find_Line');
  568.    end
  569.    else
  570.    begin
  571.       Find_Line := true;
  572.       Active_Line := linenum;
  573.    end;
  574. end;
  575.  
  576.  
  577. function GS_Edit_Objt.Get_Line_Mem(lth : integer) : pointer;
  578. var
  579.    i : longint;
  580.    p : GS_Edit_Pntr;
  581. begin
  582.    GetMem(Work_Line,lth+15);
  583.    if First_Line = nil then
  584.    begin
  585.       First_Line := Work_Line;
  586.       End_Line := Work_Line;
  587.       Work_Line^.Next_Line := nil;
  588.       Work_Line^.Prev_Line := nil;
  589.       Active_Line := 1;
  590.    end else
  591.    begin
  592.       p := First_Line;
  593.       i := 1;
  594.       while (i < Active_Line) and (p^.Next_Line <> nil) do
  595.       begin
  596.          p := p^.Next_Line;
  597.          inc(i);
  598.       end;
  599.       Work_Line^.Next_Line := p^.Next_Line;
  600.       p^.Next_Line := Work_Line;
  601.       Work_Line^.Prev_Line := p;
  602.       Work_Line^.Next_Line^.Prev_Line := Work_Line;
  603.       inc(Active_Line);
  604.    end;
  605.    Work_Line^.Return_Cod := $0D;
  606.    Work_Line^.Line_Size := lth+15;
  607.    Work_Line^.Valu_Line := '';
  608.    inc(Total_Lines);
  609.    Get_Line_Mem := Work_Line;
  610. end;
  611.  
  612. Procedure GS_Edit_Objt.Rel_Line_Mem(linenum : integer);
  613. var
  614.    wl : GS_Edit_Pntr;
  615. begin
  616.    if First_Line = nil then exit;
  617.    if not Find_Line(linenum) then exit;
  618.    if Work_Line = First_Line then
  619.    begin
  620.       First_Line := Work_Line^.Next_Line;
  621.       if First_Line <> nil then First_Line^.Prev_Line := nil;
  622.    end
  623.    else
  624.    begin
  625.       wl := Work_Line^.Prev_Line;
  626.       Work_Line^.Prev_Line^.Next_Line := Work_Line^.Next_Line;
  627.       if Work_Line^.Next_Line <> nil then
  628.          Work_Line^.Next_Line^.Prev_Line := Work_Line^.Prev_Line;
  629.    end;
  630.    FreeMem(Work_Line,Work_Line^.Line_Size);
  631.    dec(Total_Lines);
  632.    if Total_Lines < Active_Line then Active_Line := Total_Lines;
  633.    if not Find_line(Active_Line) then ShowError(710,'Rel_Line_Mem');
  634. end;
  635.  
  636. Procedure GS_Edit_Objt.Show_Lines(b, e : integer);
  637. var
  638.    i,
  639.    j : integer;
  640.    p : pointer;
  641.    a : longint;
  642. begin;
  643.    if First_Line = nil then exit;
  644.    p := Work_Line;
  645.    a := Active_Line;
  646.    if b > Total_Lines then b := Total_Lines;
  647.    if e > Total_Lines then e := Total_Lines;
  648.    if e >= b + Lines_Avail then e := pred(b+Lines_Avail);
  649.    if not Find_Line(b) then
  650.    begin
  651.       ShowError(710,'Show_Lines');
  652.       Work_Line := p;
  653.       Active_Line := a;
  654.       exit;
  655.    end;
  656.    Screen_Top := b;
  657.    j := 1;
  658.    ClrScr;
  659.    for i := b to e do
  660.    begin
  661.       gotoxy(1,j);
  662.       inc(j);
  663.       write(Work_Line^.Valu_Line);
  664.       ClrEol;
  665.       Work_Line := Work_Line^.Next_Line;
  666.    end;
  667.    Work_Line := p;
  668.    Active_Line := a;
  669. end;
  670.  
  671.  
  672. Procedure GS_Edit_Objt.WordWrap(Fline : string);
  673. var
  674.    lCnt : integer;                    {Counter for line length in characters}
  675.    linterm : byte;                    {Holds line termination code}
  676.    linchr : boolean;
  677.    wrapped : boolean;
  678.    A_L    : longint;
  679.    wLine  : string;
  680.  
  681.  
  682.    function WrapLine : boolean;
  683.    BEGIN                       { WordWrap }
  684.       if (length(wline) <= Edit_Lgth) then
  685.       begin
  686.          WrapLine := false;
  687.          exit;
  688.       end;
  689.       WrapLine := true;
  690.       lCnt := Edit_Lgth+1;
  691.       linchr := false;
  692.       while (not linchr) and (lcnt > 0) do
  693.       begin
  694.          case wline[lCnt] of
  695.             ' '  :  linchr := true;
  696.             '-'  :  linchr := true;
  697.             else    dec(lCnt);
  698.          end;
  699.                                       {Repeat search for space or hyphen until}
  700.                                       {found or current line exhausted}
  701.       end;
  702.       if (lCnt = 0) then lcnt := Edit_Lgth;
  703.                                       {If no break point, truncate line}
  704.       Temp_Line := wline;
  705.       delete(Temp_Line,1,lCnt);
  706.       wline[0] := chr(lcnt);
  707.                                       {Get string up to cursor to split line}
  708.       if (CursorPos < length(wline)) and
  709.          ((Temp_Line = ' ') or (Temp_Line = '')) then
  710.       begin
  711.          WrapLine := false;
  712.          exit;
  713.       end;
  714.    end;
  715.  
  716. BEGIN
  717.    wrapped := false;
  718.    wline := Fline;
  719.    A_L := Active_Line;
  720.    while WrapLine do
  721.    begin
  722.       wrapped := true;
  723.       Work_Line^.Valu_Line := wline;
  724.       linterm := Work_Line^.Return_Cod;
  725.       Work_Line^.Return_Cod := $8D;   {Insert soft return character}
  726.       if linterm = $0D then
  727.       begin
  728.          Work_Line := Get_Line_Mem(Edit_Lgth);
  729.          Work_Line^.Return_Cod := linterm;
  730.       end
  731.       else
  732.       begin
  733.          if not Find_Line(succ(Active_Line)) then
  734.          begin
  735.             Work_Line := Get_Line_Mem(Edit_Lgth);
  736.             Work_Line^.Return_Cod := linterm;
  737.          end;
  738.       end;
  739.       wline := Temp_Line + Work_Line^.Valu_Line;
  740.    end;
  741.    Work_Line^.Valu_Line := wline;
  742.    if not wrapped then exit;
  743.    if not Find_Line(A_L) then
  744.    begin
  745.       ShowError(710,'WordWrap');
  746.    end;
  747.    if (CursorPos > length(Work_Line^.Valu_Line)) and
  748.       (CursorPos <> Edit_Lgth+1) then
  749.    begin
  750.       CursorPos := CursorPos - length(Work_Line^.Valu_Line);
  751.       if not Find_Line(succ(Active_Line)) then
  752.       begin
  753.          ShowError(710,'WordWrap 2');
  754.       end;
  755.    end;
  756.    if ((succ(Active_Line)) - Screen_Top) > Lines_Avail then
  757.    begin
  758.       Screen_Top := (succ(Active_Line)) - Lines_Avail;
  759.    end;
  760.    Show_Lines(Screen_Top, (Screen_Top-1) + Lines_Avail);
  761.    CursorLine := (succ(Active_Line)) - Screen_Top;
  762. end;                         {WordWrap}
  763.  
  764. begin
  765.    StatWin.InitWin(1,23,80,25,Yellow,Black,LightGray,Black,LightGray,
  766.                    true,'',true);
  767.    EditWin.InitWin(1,1,80,22,LightGray,Black,LightGray,Black,LightGray,
  768.                    false,'',true);
  769.    HelpWin.InitWin(29,2,51,20,Yellow,Black,Yellow,Black,LightGray,
  770.                    true,'[ Edit Help ]',true);
  771. end.
  772.